package de.fhtrier.gdw2.ships.network;

import de.fhtrier.gdw.commons.netcode.NetConnection;
import de.fhtrier.gdw.commons.netcode.NetReception;
import de.fhtrier.gdw.commons.netcode.datagram.INetDatagram;
import de.fhtrier.gdw2.ships.SpaceshipGame;
import de.fhtrier.gdw2.ships.network.datagrams.ConnectDatagram;
import de.fhtrier.gdw2.ships.network.datagrams.DatagramFactory;
import de.fhtrier.gdw2.ships.network.datagrams.DatagramType;
import de.fhtrier.gdw2.ships.network.datagrams.LevelDatagram;
import de.fhtrier.gdw2.ships.states.GameplayState;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 *
 * @author Lusito
 */
public class NetGameServer extends NetGame {

	private NetReception reception;
	private List<NetConnection> clients = new ArrayList<>();

	public NetGameServer(String ip, int port) {
		try {
			reception = new NetReception(ip, port, 1, new DatagramFactory());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public boolean isClient() {
		return false;
	}

	@Override
	public boolean isServer() {
		return reception != null && reception.isRunning();
	}

	@Override
	public void shutdown() {
		if (reception != null) {
			for(NetConnection client: clients) {
				client.shutdown();
			}
			clients.clear();
			reception.shutdown();
			reception = null;
		}
	}

	public void getNewConnections() {
		if (reception == null || !reception.isRunning()) {
			return;
		}

		NetConnection connection = reception.getNextNewConnection();
		while (connection != null) {
			clients.add(connection);
			onClientConnect(connection);
			connection = reception.getNextNewConnection();
		}
	}

	@Override
	public void handleIncoming() {
		if (isServer()) {
			getNewConnections();

			Iterator<NetConnection> it = clients.iterator();
			while (it.hasNext()) {
				NetConnection client = it.next();
				
				while (client.hasIncoming()) {
					INetDatagram datagram = client.receive();
					if (datagram != null)
						handleDatagram(client, datagram);
				}

				if (!client.isConnected()) {
					onClientDisconnect(client);
					it.remove();
					continue;
				}
			}
		}
	}

	@Override
	public void handleOutgoing() {
		if (isServer()) {
			for (NetConnection client : clients)
				client.sendPendingDatagrams();
		}
	}

	public void handleDatagram(NetConnection client, INetDatagram datagram) {
		GameplayState state = (GameplayState)SpaceshipGame.instance.getState(SpaceshipGame.GAMESTATE);
		
		switch (datagram.getType()) {
			case DatagramType.CONNECT:
				handleConnect(client, (ConnectDatagram) datagram);
				break;
            case DatagramType.LEVEL:
                
                state.receiveLevelDatagram((LevelDatagram)datagram);
                break;
            case DatagramType.GAMEOVER:            	
            	break;
		}
	}

	private void handleConnect(NetConnection client, ConnectDatagram datagram) {
		if(!client.isAccepted()) {
			client.setAccepted(true);
            client.send(new ConnectDatagram("Server"));
            client.sendPendingDatagrams();
            SpaceshipGame.changeState(SpaceshipGame.GAMESTATE);
		}
	}

	public void onClientConnect(NetConnection client) {
	}

	public void onClientDisconnect(NetConnection client) {
	}

	@Override
	public void send(INetDatagram datagram) {
		if (isServer()) {
			for (NetConnection client : clients) {
				client.send(datagram);
			}
		}
	}

	@Override
	public void sendEvent(byte type, short id, short param1, short param2) {
		if (isServer()) {
			for (NetConnection client : clients) {
				client.sendEvent(type, id, param1, param2);
			}
		}
	}
}
